1.1 Activity 的生命周期全面分析
- onStart 和 onResume 的区别是 onStart 此时 Activity 已经可见,但是还没有出现在前台,无法和用户交互。onResume 的时候 Activity 在前台,获取到焦点能与用户交互。
- 新 Activity 是透明主题时,旧 Activity 不会走 onStop
- Activity 切换时,旧 Activity 的 onPause 会先执行,然后才会启动新的 Activity
- Activity 在异常情况下被回收时,onSaveInstanceState 方法会被回调,回调时机是在onStop 之前,当 Activity 被重新创建的时候,onRestoreInstanceState 方法会被回调,时序在 onStart 之后
- 当 Activity 被销毁并重新创建后,可恢复的位置可以选择 onRestoreInstanceState 和 onCreate ,二者的区别是 onRestoreInstanceState 一旦被调用,其参数 Bundle savedInstanceState 一定是有值的,我们不用额外判断是否为空;但是在 onCreate 里必须判断是否为空,官方推荐采用 onRestoreInstanceState 去恢复数据
1.2 Activity 的 LaunchMode
- standard 系统默认。每次启动会重新创建新的实例,谁启动了这个Activity,这个Activity 就在谁的栈里
- singleTop 栈顶复用模式。如果新的 Activity 已经位于任务栈的栈顶,那么此Activity不会被重新创建,该 Activity 的 onNewIntent 方法会被回调,onCreate 和 onStart 并不会被调用
- singleTask 栈内复用模式。只要该 Activity 在一个栈中存在,都不会重新创建,onNewIntent 会被回调。如果不存在,系统会先寻找是否存在需要的栈,如果不存在该栈,就创建一个任务栈,然后把这个 Activity 放进去;如果存在,就会创建到已经存在的这个栈中
- singleInstance 单实例模式。具有此种模式的 Activity 只能单独存在于一个任务栈
什么是任务栈?
默认情况下所有 Activity 所需的任务栈的名字为应用的包名,可以为每个 Activity 都单独在 AndroidManifest 指定 TaskAffinity 属性。当 TaskAffinity 和 singleTask 启动模式配对使用的时候,待启动的 Activity 会运行在名字和 TaskAffinity 相同的任务栈中
Activity 的 Flags
FLAG_ACTIVITY_NEW_TASK
它与 launchMode=”singleTask” 具有相同的行为。实际上,并不是完全相同!很少单独使用 FLAG_ACTIVITY_NEW_TASK,通常与 FLAG_ACTIVITY_CLEAR_TASK 或 FLAG_ACTIVITY_CLEAR_TOP 联合使用。在相互跳转的两个 Activity的 android:taskAffinity 相同的情况下 ,单独使用 FLAG_ACTIVITY_NEW_TASK 不会产生任何效果
FLAG_ACTIVITY_SINGLE_TOP
它与 launchMode=”singleTop” 具有相同的行为
FLAG_ACTIVITY_CLEAR_TOP
当它启动时,在同一个任务栈中所有位于它上面的 Activity 都要出栈。FLAG_ACTIVITY_CLEAR_TOP 和 FLAG_ACTIVITY_NEW_TASK 两者同时使用,就能达到和 launchMode=”singleTask” 一样的效果
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
具有这个标记的 Activity 不会出现在历史 Activity 的列表中,他等同于在 XML 中指定 Activity 的属性 android:excludeFromRecents=’true’
FLAG_ACTIVITY_CLEAR_TASK
使用 FLAG_ACTIVITY_CLEAR_TASK 时,通常会包含 FLAG_ACTIVITY_NEW_TASK 。这样做的目的是启动 Activity 时,清除之前已经存在的 Activity 实例所在的 task ;这自然也就清除了之前存在的 Activity 实例
通过 AndroidManifest 指定启动模式和通过在 Intent 中设置标志位来指定启动模式,二者的区别是什么?
- 优先级。当同时使用 launchMode 和上面的 FLAG_ACTIVITY_NEW_TASK 等标签时,以FLAG_ACTIVITY_NEW_TASK 为标准。也就是说,代码的优先级比 manifest 中配置文件的优先级更高
- 限定范围。在 manifest 中无法配置 FLAG_ACTIVITY_CLEAR_TOP 等标识,在 Intent 中无法指定 singleInstance 模式
1.3 IntentFilter 的匹配规则
action 匹配规则:要求 Intent 中的 action 存在且必须和过滤规则中的其中一个相同,区分大小写
category 匹配规则:系统会默认加上一个 android.intent.category.DEAFAULT ,所以Intent 中可以不存在 category ,但如果存在就必须匹配其中一个
data 匹配规则:data 由两部分组成,mimeType 和 URI。mimeType 指媒体类型,比如 image/jpeg、video/*,可以表示图片、文本、视频等不同的媒体格式,而 URI 中包含的数据就比较多了,下面是 URI 的结构:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
这里再给几个实际的例子就好理解了
content://com.example.project:200/folder/subfolder/etc
https://www.google.com:443/search/info要求 Intent 中必须含有 data 数据。如果没有指定 URI,URI 的默认值为 content 和file(schema)
判断是否有 Activity 匹配我们的隐式 Intent:
采用 PackageManager 的 resolveActivity 方法或者 Intent 的 resolveActivity 方法,果它们找不到匹配的 Activity 就会返回 null。另外,PackageManager 还提供了queryIntentActivities 方法,这个方法和 resolveActivity 方法不同的是:它不是返回最佳匹配的 Activity 信息而是返回所有成功匹配的 Activity 信息
public abstract List<ResolveInfo>queryIntentActivities(Intent intent,int fladgs);
public abstract ResolveInfo resolveActivity(Intent intent,int flags);